package wasnake.grid;

import java.io.Serializable;
import java.util.ArrayList;

/**
 * <code>AbstractGrid</code> contains the methods that are common to grid
 * implementations.
 *
 * CREDIT TO: GridWorld case study
 */

public abstract class AbstractGrid<E> implements Grid<E>, Serializable{
    
    @Override
    public ArrayList<E> getNeighbors(Location loc) {
        ArrayList<E> neighbors = new ArrayList<E>();
        for (Location neighborLoc : getOccupiedAdjacentLocations(loc))
            neighbors.add(get(neighborLoc));
        return neighbors;
    }
    
    @Override
    public ArrayList<E> getNeighborsInRange(Location loc, int range) {
            ArrayList<E> neighbors = new ArrayList<E>();

            Location hotspot;
            for(int row = loc.getRow() - range; row < loc.getRow() + range; row++) {
                    for(int col = loc.getCol() - range; col < loc.getCol() + range; col++) {
                            hotspot = new Location(row, col);
                            if(!hotspot.equals(loc) && isValid(hotspot) && get(hotspot) != null) {
                                    neighbors.add(get(hotspot));
                            }
                    }
            }

            return neighbors;
    }

    @Override
    public ArrayList<Location> getValidAdjacentLocations(Location loc) {
        ArrayList<Location> locs = new ArrayList<Location>();

        for (Direction dir : Direction.values()) {
            Location neighborLoc = loc.getAdjacentLocation(dir);
            if (isValid(neighborLoc))
                locs.add(neighborLoc);
        }        
        return locs;
    }

    @Override
    public ArrayList<Location> getEmptyAdjacentLocations(Location loc) {
        ArrayList<Location> locs = new ArrayList<Location>();
        for (Location neighborLoc : getValidAdjacentLocations(loc)) {
            if (get(neighborLoc) == null)
                locs.add(neighborLoc);
        }
        return locs;
    }

    @Override
    public ArrayList<Location> getOccupiedAdjacentLocations(Location loc) {
        ArrayList<Location> locs = new ArrayList<Location>();
        for (Location neighborLoc : getValidAdjacentLocations(loc)) {
            if (get(neighborLoc) != null)
                locs.add(neighborLoc);
        }
        return locs;
    }

    /**
     * Creates a string that describes this grid.
     * @return a string with descriptions of all objects in this grid (not
     * necessarily in any particular order), in the format {loc=obj, loc=obj,
     * ...}
     */
    @Override
    public String toString() {
        String s = "{";
        for (Location loc : getOccupiedLocations()) {
            if (s.length() > 1)
                s += ", ";
            s += loc + "=" + get(loc);
        }
        return s + "}";
    }
}